{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python Practice 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Open a `heights.csv` file with `np.loadtxt()` function. Be sure to set a correct \n",
    "delimiter in the `np.loadtxt()` function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "heights = np.loadtxt('heights.csv', delimiter=',')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's plot the data distribution with `plt.hist()` function. Since we have a 2D array,\n",
    "we might need to convert it to th 1D array first by calling the `flatten()` **method** of an array.\n",
    "\n",
    "Generally speaking, method is usually a certain function that belongs to a class.\n",
    "This function acts directly on the object it was called by (in our case - numpy array). \n",
    "You can think of the following analogy:\n",
    "\n",
    "```python\n",
    "def mean(array):\n",
    "    return np.mean(array)\n",
    "```\n",
    "and\n",
    "```python\n",
    "array.mean()\n",
    "```\n",
    "are equivalent. The first one is a function that takes an array as an argument, while the second one is a method that belongs to the array class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGdCAYAAAAxCSikAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAmEElEQVR4nO3de1CUV4L//w+o4LWbRYWGFbzloo7oOCTBrmTcbGQFwiRmJLvRYROddXXjQnYiM45hymjibg2umYrZpIzuViWaqYnJjFXRVHRilmDEyYokklDeEkotDGahIaMFrTjcz/eP+fH8tiNeGsE+wPtV1VX085x++pw8Qr/TFwgzxhgBAABYLDzUEwAAALgeggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QaHegLd0dHRoerqao0aNUphYWGhng4AALgBxhhdvHhR8fHxCg8P7jmTPhks1dXVSkhICPU0AABAN5w7d07jxo0L6jZ9MlhGjRol6c8LdrlcIZ4NAAC4EX6/XwkJCc7jeDD6ZLB0vgzkcrkIFgAA+pjuvJ2DN90CAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsF1SwbNmyRTNmzHD+6KDX69X777/v7G9qalJOTo5Gjx6tkSNHKisrS7W1tQHHqKqqUmZmpoYPH66YmBitWrVKbW1tPbMaAADQLwUVLOPGjdOGDRtUVlamI0eO6IEHHtD8+fN14sQJSdLKlSv13nvvaefOnSouLlZ1dbUWLFjg3L69vV2ZmZlqaWnRoUOH9MYbb2j79u1au3Ztz64KAAD0K2HGGHMzB4iOjtYLL7ygRx99VGPHjtWOHTv06KOPSpK+/PJLTZ06VSUlJZo9e7bef/99/eAHP1B1dbViY2MlSVu3btXq1av1zTffKCIi4obu0+/3y+12q6GhQS6X62amDwDoQyY8s7fXjn12Q2avHRt/djOP391+D0t7e7vefvttNTY2yuv1qqysTK2trUpNTXXGTJkyRYmJiSopKZEklZSUKCkpyYkVSUpLS5Pf73eepQEAAPi2wcHe4NixY/J6vWpqatLIkSO1a9cuTZs2TeXl5YqIiFBUVFTA+NjYWPl8PkmSz+cLiJXO/Z37rqa5uVnNzc3Odb/fH+y0AQBAHxb0Myx33nmnysvLVVpaqhUrVmjx4sU6efJkb8zNUVBQILfb7VwSEhJ69f4AAIBdgg6WiIgI3XbbbUpOTlZBQYFmzpyp//iP/5DH41FLS4vq6+sDxtfW1srj8UiSPB7PFZ8a6rzeOaYr+fn5amhocC7nzp0LdtoAAKAPu+nfw9LR0aHm5mYlJydryJAhKioqcvZVVFSoqqpKXq9XkuT1enXs2DHV1dU5YwoLC+VyuTRt2rSr3kdkZKTzUerOCwAAGDiCeg9Lfn6+MjIylJiYqIsXL2rHjh06cOCAPvjgA7ndbi1dulR5eXmKjo6Wy+XSU089Ja/Xq9mzZ0uS5s2bp2nTpunxxx/Xxo0b5fP5tGbNGuXk5CgyMrJXFggAAPq+oIKlrq5OTzzxhGpqauR2uzVjxgx98MEH+pu/+RtJ0qZNmxQeHq6srCw1NzcrLS1Nr776qnP7QYMGac+ePVqxYoW8Xq9GjBihxYsXa/369T27KgAA0K/c9O9hCQV+DwsADEz8Hpa+LSS/hwUAAOBWIVgAAID1CBYAAGA9ggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QgWAABgPYIFAABYj2ABAADWI1gAAID1CBYAAGA9ggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QgWAABgPYIFAABYj2ABAADWI1gAAID1CBYAAGA9ggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QgWAABgPYIFAABYj2ABAADWI1gAAID1CBYAAGA9ggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QgWAABgPYIFAABYL6hgKSgo0N13361Ro0YpJiZGjzzyiCoqKgLG3H///QoLCwu4PPnkkwFjqqqqlJmZqeHDhysmJkarVq1SW1vbza8GAAD0S4ODGVxcXKycnBzdfffdamtr0y9+8QvNmzdPJ0+e1IgRI5xxy5Yt0/r1653rw4cPd75ub29XZmamPB6PDh06pJqaGj3xxBMaMmSIfvnLX/bAkgAAQH8TVLDs27cv4Pr27dsVExOjsrIyzZkzx9k+fPhweTyeLo/x3//93zp58qQ+/PBDxcbG6rvf/a7+9V//VatXr9Zzzz2niIiIbiwDAAD0Zzf1HpaGhgZJUnR0dMD2N998U2PGjNH06dOVn5+vy5cvO/tKSkqUlJSk2NhYZ1taWpr8fr9OnDjR5f00NzfL7/cHXAAAwMAR1DMs/1dHR4eefvpp3XvvvZo+fbqz/Uc/+pHGjx+v+Ph4HT16VKtXr1ZFRYXeeecdSZLP5wuIFUnOdZ/P1+V9FRQU6Pnnn+/uVAEAQB/X7WDJycnR8ePH9fHHHwdsX758ufN1UlKS4uLiNHfuXJ05c0aTJ0/u1n3l5+crLy/Pue73+5WQkNC9iQMAgD6nWy8J5ebmas+ePfroo480bty4a45NSUmRJJ0+fVqS5PF4VFtbGzCm8/rV3vcSGRkpl8sVcAEAAANHUMFijFFubq527dql/fv3a+LEide9TXl5uSQpLi5OkuT1enXs2DHV1dU5YwoLC+VyuTRt2rRgpgMAAAaIoF4SysnJ0Y4dO/Tuu+9q1KhRzntO3G63hg0bpjNnzmjHjh168MEHNXr0aB09elQrV67UnDlzNGPGDEnSvHnzNG3aND3++OPauHGjfD6f1qxZo5ycHEVGRvb8CgEAQJ8XZowxNzw4LKzL7du2bdOSJUt07tw5/f3f/72OHz+uxsZGJSQk6Ic//KHWrFkT8DLOV199pRUrVujAgQMaMWKEFi9erA0bNmjw4BvrJ7/fL7fbrYaGBl4eAoABZMIze0M9haCd3ZAZ6ilY42Yev4N6huV6bZOQkKDi4uLrHmf8+PH6/e9/H8xdAwCAAYy/JQQAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6QQVLQUGB7r77bo0aNUoxMTF65JFHVFFRETCmqalJOTk5Gj16tEaOHKmsrCzV1tYGjKmqqlJmZqaGDx+umJgYrVq1Sm1tbTe/GgAA0C8FFSzFxcXKycnR4cOHVVhYqNbWVs2bN0+NjY3OmJUrV+q9997Tzp07VVxcrOrqai1YsMDZ397erszMTLW0tOjQoUN64403tH37dq1du7bnVgUAAPqVMGOM6e6Nv/nmG8XExKi4uFhz5sxRQ0ODxo4dqx07dujRRx+VJH355ZeaOnWqSkpKNHv2bL3//vv6wQ9+oOrqasXGxkqStm7dqtWrV+ubb75RRETEde/X7/fL7XaroaFBLperu9MHAPQxE57ZG+opBO3shsxQT8EaN/P4fVPvYWloaJAkRUdHS5LKysrU2tqq1NRUZ8yUKVOUmJiokpISSVJJSYmSkpKcWJGktLQ0+f1+nThxosv7aW5ult/vD7gAAICBo9vB0tHRoaefflr33nuvpk+fLkny+XyKiIhQVFRUwNjY2Fj5fD5nzP+Nlc79nfu6UlBQILfb7VwSEhK6O20AANAHdTtYcnJydPz4cb399ts9OZ8u5efnq6GhwbmcO3eu1+8TAADYY3B3bpSbm6s9e/bo4MGDGjdunLPd4/GopaVF9fX1Ac+y1NbWyuPxOGM++eSTgON1foqoc8y3RUZGKjIysjtTBQAA/UBQz7AYY5Sbm6tdu3Zp//79mjhxYsD+5ORkDRkyREVFRc62iooKVVVVyev1SpK8Xq+OHTumuro6Z0xhYaFcLpemTZt2M2sBAAD9VFDPsOTk5GjHjh169913NWrUKOc9J263W8OGDZPb7dbSpUuVl5en6OhouVwuPfXUU/J6vZo9e7Ykad68eZo2bZoef/xxbdy4UT6fT2vWrFFOTg7PogAAgC4FFSxbtmyRJN1///0B27dt26YlS5ZIkjZt2qTw8HBlZWWpublZaWlpevXVV52xgwYN0p49e7RixQp5vV6NGDFCixcv1vr1629uJQAAoN+6qd/DEir8HhYAGJj4PSx9W8h+DwsAAMCtQLAAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAekEHy8GDB/XQQw8pPj5eYWFh2r17d8D+JUuWKCwsLOCSnp4eMObChQvKzs6Wy+VSVFSUli5dqkuXLt3UQgAAQP8VdLA0NjZq5syZ2rx581XHpKenq6amxrm89dZbAfuzs7N14sQJFRYWas+ePTp48KCWL18e/OwBAMCAMDjYG2RkZCgjI+OaYyIjI+XxeLrc98UXX2jfvn369NNPddddd0mSXnnlFT344IP61a9+pfj4+GCnBAAA+rleeQ/LgQMHFBMTozvvvFMrVqzQ+fPnnX0lJSWKiopyYkWSUlNTFR4ertLS0i6P19zcLL/fH3ABAAADR48HS3p6un7961+rqKhI//7v/67i4mJlZGSovb1dkuTz+RQTExNwm8GDBys6Olo+n6/LYxYUFMjtdjuXhISEnp42AACwWNAvCV3PwoULna+TkpI0Y8YMTZ48WQcOHNDcuXO7dcz8/Hzl5eU51/1+P9ECAMAA0usfa540aZLGjBmj06dPS5I8Ho/q6uoCxrS1tenChQtXfd9LZGSkXC5XwAUAAAwcvR4sX3/9tc6fP6+4uDhJktfrVX19vcrKypwx+/fvV0dHh1JSUnp7OgAAoA8K+iWhS5cuOc+WSFJlZaXKy8sVHR2t6OhoPf/888rKypLH49GZM2f085//XLfddpvS0tIkSVOnTlV6erqWLVumrVu3qrW1Vbm5uVq4cCGfEAIAAF0K+hmWI0eOaNasWZo1a5YkKS8vT7NmzdLatWs1aNAgHT16VA8//LDuuOMOLV26VMnJyfrDH/6gyMhI5xhvvvmmpkyZorlz5+rBBx/Ufffdp//6r//quVUBAIB+JehnWO6//34ZY666/4MPPrjuMaKjo7Vjx45g7xoAAAxQ/C0hAABgPYIFAABYj2ABAADWI1gAAID1CBYAAGA9ggUAAFivx/+WEAAA+P9NeGZvrx377IbMXju2bXiGBQAAWI9gAQAA1iNYAACA9QgWAABgPYIFAABYj2ABAADWI1gAAID1CBYAAGA9ggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QgWAABgPYIFAABYj2ABAADWI1gAAID1CBYAAGA9ggUAAFiPYAEAANYjWAAAgPUIFgAAYD2CBQAAWI9gAQAA1iNYAACA9QaHegIAgP5nwjN7Qz0F9DM8wwIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKwXdLAcPHhQDz30kOLj4xUWFqbdu3cH7DfGaO3atYqLi9OwYcOUmpqqU6dOBYy5cOGCsrOz5XK5FBUVpaVLl+rSpUs3tRAAANB/BR0sjY2NmjlzpjZv3tzl/o0bN+rll1/W1q1bVVpaqhEjRigtLU1NTU3OmOzsbJ04cUKFhYXas2ePDh48qOXLl3d/FQAAoF8bHOwNMjIylJGR0eU+Y4xeeuklrVmzRvPnz5ck/frXv1ZsbKx2796thQsX6osvvtC+ffv06aef6q677pIkvfLKK3rwwQf1q1/9SvHx8TexHAAA0B/16HtYKisr5fP5lJqa6mxzu91KSUlRSUmJJKmkpERRUVFOrEhSamqqwsPDVVpa2uVxm5ub5ff7Ay4AAGDg6NFg8fl8kqTY2NiA7bGxsc4+n8+nmJiYgP2DBw9WdHS0M+bbCgoK5Ha7nUtCQkJPThsAAFiuT3xKKD8/Xw0NDc7l3LlzoZ4SAAC4hXo0WDwejySptrY2YHttba2zz+PxqK6uLmB/W1ubLly44Iz5tsjISLlcroALAAAYOHo0WCZOnCiPx6OioiJnm9/vV2lpqbxeryTJ6/Wqvr5eZWVlzpj9+/ero6NDKSkpPTkdAADQTwT9KaFLly7p9OnTzvXKykqVl5crOjpaiYmJevrpp/Vv//Zvuv322zVx4kQ9++yzio+P1yOPPCJJmjp1qtLT07Vs2TJt3bpVra2tys3N1cKFC/mEEAAA6FLQwXLkyBH99V//tXM9Ly9PkrR48WJt375dP//5z9XY2Kjly5ervr5e9913n/bt26ehQ4c6t3nzzTeVm5uruXPnKjw8XFlZWXr55Zd7YDkAAKA/CjPGmFBPIlh+v19ut1sNDQ28nwUALDThmb2hnsKAcHZDZqinEJSbefzuE58SAgAAAxvBAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHqDQz0BG014Zm+vHPfshsxeOS4AAP0dz7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAej0eLM8995zCwsICLlOmTHH2NzU1KScnR6NHj9bIkSOVlZWl2tranp4GAADoR3rlGZbvfOc7qqmpcS4ff/yxs2/lypV67733tHPnThUXF6u6uloLFizojWkAAIB+olf++OHgwYPl8Xiu2N7Q0KDXXntNO3bs0AMPPCBJ2rZtm6ZOnarDhw9r9uzZvTEdAADQx/XKMyynTp1SfHy8Jk2apOzsbFVVVUmSysrK1NraqtTUVGfslClTlJiYqJKSkqser7m5WX6/P+ACAAAGjh4PlpSUFG3fvl379u3Tli1bVFlZqe9///u6ePGifD6fIiIiFBUVFXCb2NhY+Xy+qx6zoKBAbrfbuSQkJPT0tAEAgMV6/CWhjIwM5+sZM2YoJSVF48eP1+9+9zsNGzasW8fMz89XXl6ec93v9xMtAAAMIL3+seaoqCjdcccdOn36tDwej1paWlRfXx8wpra2tsv3vHSKjIyUy+UKuAAAgIGj14Pl0qVLOnPmjOLi4pScnKwhQ4aoqKjI2V9RUaGqqip5vd7engoAAOijevwloZ/97Gd66KGHNH78eFVXV2vdunUaNGiQFi1aJLfbraVLlyovL0/R0dFyuVx66qmn5PV6+YQQAAC4qh4Plq+//lqLFi3S+fPnNXbsWN133306fPiwxo4dK0natGmTwsPDlZWVpebmZqWlpenVV1/t6WkAAIB+pMeD5e23377m/qFDh2rz5s3avHlzT981AADop/hbQgAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOsRLAAAwHoECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsEC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eHj4FS+f9DVff/21zp8/7/x77S/ntNNrr72m5ORkzZw587pjbTyn13tMuZGftV6vV8eOHQsI0c4onzZtWlCTGbDefvttExkZabZv325Onjxpli9fbqKiogLeydzXrFixwrjdbnPgwAFTU1PjXC5fvmyMMeb06dNm/fr15siRI6aystK8++67ZtKkSWbOnDkhnnnwfvrTn5oDBw6YyspK8z//8z8mNTXVjBkzxtTV1RljjHnyySdNYmKi2b9/vzly5Ijxer3G6/WGeNbd097ebhITE83q1asDtvf183nx4kXz+eefm88//9xIMi+++KL5/PPPnU/HbNiwwURFRZl3333XHD161MyfP99MnDjR/OlPf3KOkZ6ebmbNmmVKS0vNxx9/bG6//XazaNGiUC2pS9daZ0tLi3n44YfNuHHjTHl5ecD3becnKA4dOmQ2bdpkysvLzZkzZ8xvfvMbM3bsWPPEE0+EeGVXutZaL168aH72s5+ZkpISU1lZaT788EPzve99z9x+++2mqanJOUZfP6edGhoazPDhw82WLVuuuH1fOafXe0wx5vo/a9va2sz06dPNvHnzTHl5udm3b58ZO3asyc/PD2ouAzpYjDHmlVdeMYmJiSYiIsLcc8895vDhw6Ge0k2R1OVl27ZtxhhjqqqqzJw5c0x0dLSJjIw0t912m1m1apVpaGgI7cS74bHHHjNxcXEmIiLC/OVf/qV57LHHzOnTp539f/rTn8w///M/m7/4i78ww4cPNz/84Q9NTU1NCGfcfR988IGRZCoqKgK29/Xz+dFHH3X573Xx4sXGmD9/tPnZZ581sbGxJjIy0sydO/eK/wbnz583ixYtMiNHjjQul8v8+Mc/NhcvXgzBaq7uWuusrKy86vftRx99ZIwxpqyszKSkpBi3222GDh1qpk6dan75y18GPMjb4lprvXz5spk3b54ZO3asGTJkiBk/frxZtmzZFf+T2NfPaaf//M//NMOGDTP19fVX3L6vnNPrPaYYc2M/a8+ePWsyMjLMsGHDzJgxY8xPf/pT09raGtRcwv6/CQEAAFhrwL6HBQAA9B0ECwAAsB7BAgAArEewAAAA6xEsAADAegQLAACwHsECAACsR7AAAADrESwAAMB6BAsAALAewQIAAKxHsAAAAOv9Pyj0+qRDoJmbAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "flattened_heights = heights.flatten()\n",
    "plt.hist(flattened_heights, bins=20)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We clearly see that something is wrong with the data. Let's try to find out\n",
    "the reason for that.\n",
    "\n",
    "First we might need to take a look, what are the exact values of those weird\n",
    "heights. To do that, we need to select all the heights that are less than\n",
    "10 (for instance) by using the `heights[heights < 10]` syntax."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.74, 1.61, 1.64, 1.55, 1.56, 1.68, 1.62, 1.76, 1.69, 1.7 , 1.63,\n",
       "       1.44, 1.5 , 1.62, 1.49, 1.73, 1.73, 1.52, 1.54, 1.61, 1.47, 1.69,\n",
       "       1.79, 1.6 , 1.79, 1.62, 1.67, 1.61, 1.62, 1.69, 1.66, 1.77, 1.63,\n",
       "       1.61, 1.6 , 1.76, 1.7 , 1.7 , 1.62, 1.81, 1.67, 1.61, 1.55, 1.5 ,\n",
       "       1.59, 1.65, 1.73, 1.49, 1.69, 1.66, 1.75, 1.62, 1.74, 1.64, 1.66,\n",
       "       1.7 , 1.71, 1.66, 1.67, 1.67, 1.67, 1.54, 1.58])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "heights[heights < 3.0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It turns out that the values are just listed in meters, not in centimeters. \n",
    "To fix this issue, let's create the function that checks if the height is less than 3 meters\n",
    "and if it is, it multiplies the height by 100 to convert it to centimeters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fix_height_units(original_heights, threshold = 3.0):\n",
    "    fixed_heights = original_heights.copy() # We don't want to modify the original array, so we make a copy\n",
    "    for i in range(len(fixed_heights)):\n",
    "        for j in range(len(fixed_heights[i])):\n",
    "            if fixed_heights[i][j] < threshold:\n",
    "                fixed_heights[i][j] = fixed_heights[i][j] * 100.0\n",
    "    return fixed_heights"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also use the advanced numpy indexing to select all the heights that are less than 3 meters\n",
    "and multiply them by 100. In this example we can use the `heights[heights < 3] = heights[heights < 3] * 100` syntax.\n",
    "What happens is that `heights < 3` returns a boolean array of the same shape as the original array.\n",
    "Each element of this array is eigher `True` or `False` depending on whether the condition is met.\n",
    "Then we use this boolean array to select only the elements that are less than 3 meters and multiply them by 100."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fix_height_units_vectorized(original_heights, threshold = 3.0):\n",
    "    fixed_heights = original_heights.copy() # We don't want to modify the original array, so we make a copy\n",
    "    fixed_heights[fixed_heights < threshold] = fixed_heights[fixed_heights < threshold] * 100\n",
    "    return fixed_heights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "fixed_heights = fix_height_units(heights, threshold = 3.0) # This is our original function\n",
    "fixed_heights_vectorized = fix_height_units_vectorized(heights, threshold=3.0) # This is our vectorized function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.allclose(fixed_heights, fixed_heights_vectorized) # This will fail if the two arrays are not equal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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NfvmtbV//3499thjcrlcKiwsDB7DNfa10tJSVVdX6y9/+Yt27typ2bNnq6SkRBs2bAge05OusZOtl+M4mjhxoj744AM988wzevPNNzV48GDl5ubqyJEjweN6zHo5MEGSs27duhO2f/zxx86PfvQj55133nEGDx7s3H///cF9O3bscCQ5W7duDW57/vnnHZfL5XzyySenYero6mjNpk6d6hQUFPzP7+nJa9bRek2ePNm5/vrr/+f3NDU1OXFxcc7atWuD23bu3OlIcmprayM1qhn/6/+X31RQUOBcffXVwa+5xtaFbBsxYoRzxx13hGy75JJLnD/+8Y+O4/Tsa+zb69XQ0OBIct55553gtuPHjzsDBgxwHn30UcdxetZ6cQfFsPb2dt1www2aO3euRowYccL+2tpaJScna/To0cFtubm5iomJUV1d3ekc1ZSNGzcqNTVV5513nm688UYdPHgwuI81+1p7e7uqqqr04x//WHl5eUpNTVV2dnbILef6+nq1tbUpNzc3uG3o0KHKyMhQbW1tFKa2xe/3q6qqSjNmzAhu4xoLddlll2nDhg365JNP5DiOXn75Ze3atUvXXnutJK6xb2ptbZWkkDuYMTExio+P16uvviqpZ60XgWLYkiVLFBsbq1tuuaXD/T6fT6mpqSHbYmNjlZKSIp/PdzpGNCc/P19r1qxRTU2NlixZok2bNmncuHE6fvy4JNbsmw4cOKCWlhYtXrxY+fn5+sc//qHrrrtOkyZN0qZNmyR9uV69e/c+4cM5PR5Pj1uvjqxevVr9+vULub3ONRZq+fLlGj58uAYNGqTevXsrPz9fK1as0BVXXCGJa+ybvgqNsrIyffrppzp27JiWLFmijz/+WPv375fUs9Yram91j5Orr6/XAw88oDfeeEMulyva43QZU6ZMCf7zBRdcoAsvvFDnnHOONm7cqGuuuSaKk9nT3t4uSSooKNCcOXMkSRdddJFee+01VVZW6sorr4zmeF3CY489pqKiopD/4kWo5cuXa8uWLdqwYYMGDx6szZs3q7i4WGlpaSF3ASDFxcXp73//u2bMmKGUlBT16tVLubm5GjdunJwe+Kbv3EEx6pVXXtGBAweUkZGh2NhYxcbG6qOPPtLvf/97ZWZmSpK8Xq8OHDgQ8n1ffPGFDh06JK/XG4Wp7Tn77LN11lln6b333pPEmn3TWWedpdjYWA0fPjxk+7Bhw4Kv4vF6vTp27JiamppCjvH7/T1uvb7tlVdeUUNDg37zm9+EbOca+9rnn3+u2267TUuXLtWECRN04YUXqqSkRJMnT9a9994riWvs20aNGqXt27erqalJ+/fvV3V1tQ4ePKizzz5bUs9aLwLFqBtuuEFvvfWWtm/fHnykpaVp7ty5euGFFyRJOTk5ampqUn19ffD7XnrpJbW3tys7Oztao5vy8ccf6+DBgxo4cKAk1uybevfurTFjxqihoSFk+65duzR48GBJX/7LMi4uTjU1NcH9DQ0N2rt3r3Jyck7rvNasXLlSo0aN0siRI0O2c419ra2tTW1tbYqJCf1V06tXr+AdPK6xjrndbg0YMEC7d+/Wtm3bVFBQIKlnrRd/4omilpaW4H/ZS9KePXu0fft2paSkKCMjQ/379w85Pi4uTl6vV+edd56kL/9LNz8/XzNnzlRlZaXa2tpUUlKiKVOmdPiS5O7gZGuWkpKi22+/XYWFhfJ6vXr//fc1b948nXvuucrLy5PU89bsVNfY3LlzNXnyZF1xxRW66qqrVF1drWeffVYbN26U9OW/JGfMmKHS0lKlpKQoKSlJN998s3JycnTppZdG6aeKrFOtmSQFAgGtXbtW99133wnfzzUWul5XXnml5s6dq8TERA0ePFibNm3SmjVrtHTpUkk97xo71XqtXbtWAwYMUEZGht5++23deuutmjhxYvBJxT1qvaL9MqKe7OWXX3YknfCYOnVqh8d/+2XGjuM4Bw8edH71q185ffv2dZKSkpzp06c7hw8fjvzwUXKyNfvss8+ca6+91hkwYIATFxfnDB482Jk5c6bj8/lCztGT1uy7XGMrV650zj33XCchIcEZOXKks379+pBzfP75585NN93knHnmmc4ZZ5zhXHfddc7+/ftP809y+nyXNXv44YedxMREp6mpqcNzcI19vV779+93pk2b5qSlpTkJCQnOeeed59x3331Oe3t78Bw96Ro71Xo98MADzqBBg5y4uDgnIyPDWbBggdPa2hpyjp6yXi7H6YHPvAEAAKbxHBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMOf/AWq3UxhIFjJXAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(fixed_heights.flatten(), bins=20)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's test the following hypothesis: \n",
    "\n",
    "\"Is the true mean that represents the sample a given sample different from the population mean? Assume that the standard deviation of the data $\\sigma = 10$. Use a 95% confidence interval.\"\n",
    "\n",
    "To do that, we need to calculate first the population mean by using the `np.mean()` function over all the heights.\n",
    "Then we need to calculate the samples means by using the `np.mean()` function over each sample, or by providing\n",
    "the `axis=1` argument to the `np.mean()` function. \n",
    "\n",
    "Given that we know the standard deviation, the number of samples and the confidence level, we can use the formula\n",
    "for the z-score:\n",
    "\n",
    "$$z_{\\bar{x}} = \\frac{\\bar{x} - \\mu}{\\frac{\\sigma}{\\sqrt{n}}}$$\n",
    "\n",
    "where $\\bar{x}$ is the sample mean, $\\mu$ is the population mean, $\\sigma$ is the standard deviation and $n$ is the number of samples."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "population_mean = np.mean(fixed_heights)\n",
    "samples_mean = np.mean(fixed_heights, axis=1)\n",
    "n = len(fixed_heights[0])\n",
    "stddev = 10.0\n",
    "\n",
    "z_score = (samples_mean - population_mean) / (stddev / np.sqrt(n))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [],
   "source": [
    "z_threshold = 1.96\n",
    "test_results = np.abs(z_score) > z_threshold"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(test_results == True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total number of samples:  100\n",
      "Number of outliers:  5\n"
     ]
    }
   ],
   "source": [
    "num_samples = len(test_results)\n",
    "num_outliers = sum(test_results == True)\n",
    "\n",
    "print(\"Total number of samples: \", num_samples)\n",
    "print(\"Number of outliers: \", num_outliers)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "metatrain",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
